package com.quanquan.user.service;

import DTO.PageDTO;
import DTO.user.UserDTO;
import base.AuthConst;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.quanquan.user.configBeans.RabbitSender;
import com.quanquan.user.dto.AccessTokenDTO;
import com.quanquan.user.dto.WeChatPersionalInfoDTO;
import com.quanquan.user.entity.User;
import com.quanquan.user.entity.otherCrm.bean.*;
import com.quanquan.user.exception.UserException;
import com.quanquan.user.repository.UserRepository;
import com.quanquan.user.request.OpenidRequestBody;
import com.quanquan.user.request.RegisterRequestBody;
import com.quanquan.user.request.UserRequestBody;
import commond.ImageOutPut;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import request.PageRequestBody;
import utils.*;

import javax.persistence.criteria.Predicate;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * 功能描述: 会员管理逻辑层
 *
 * @ClassName: UserService
 * @Author: xiaoqianh丶
 * @Date: 2019-03-12 17:50
 * @Version: V1.0
 */
@Service
public class UserService {

    @Value("${wx-params.id}")
    private String appid;

    @Value("${wx-params.secret}")
    private String secret;

    @Value("${wx-params.jsapiticket}")
    private String jsapiticket;

    @Value("${wx-params.grant}")
    private String grant;

    @Value("${wx-params.wechat_user_info_url}")
    private String wechat_user_info_url;

    @Value("${wx-parking-params.id}")
    private String parkingAppid;

    @Value("${wx-parking-params.secret}")
    private String parkingSecret;

    private static final Integer EXPIRETOKEN = 1200;

    private static final String TOKEN = "token";
    /**
     * 会员卡号
     */
    private static final String MEMBERCARDNUM = "memberCardNum";
    /**
     * 身份证
     */
    private static final String IDENTITY_CARD = "identityCard";
    /**
     * 军官证
     */
    private static final String ARMYMAN_CARD = "armymanCard";
    /**
     * 微信公众号
     */
    private static final String OFFICIAL_ACCOUNTS = "official_accounts";
    /**
     * 微信小程序
     */
    private static final String WECHAT_APPLET = "wechat_applet";


    private final UserRepository userRepository;

    private final AmqpTemplate amqpTemplate;

    private final StringRedisTemplate redisTemplate;

    private final RabbitSender rabbitSender;

    @Autowired
    private UserLevelService userLevelService;

    @Autowired
    public UserService(UserRepository userRepository, AmqpTemplate amqpTemplate, StringRedisTemplate redisTemplate, RabbitSender rabbitSender) {
        this.userRepository = userRepository;
        this.amqpTemplate = amqpTemplate;
        this.redisTemplate = redisTemplate;
        this.rabbitSender = rabbitSender;
    }


    /**
     * 登录或注册
     *
     * @param requestBody
     */
    public User loginOrRegistered(UserRequestBody requestBody, String phone) {
        List<User> users = userRepository.findUserByPhoneAndRemove(phone, 0);

        if (users.size() <= 0) {
            //新用户直接注册
            User user = new User();
            user.setId(UUIDGenerator.getUUID());
            //通过映射关系来赋值// 断点看一下
            BeanUtils.copyProperties(requestBody, user);
            try {
                String memberCardNum = getMemberCardNum();
                //生成会员卡号
                user.setMemberCardNum((memberCardNum));
            } catch (Exception e) {
                e.printStackTrace();
            }

            user.setCreateTime(DateUtils.currentDate());
            //计算过期时间
            user.setExpirationTime(getExpirationTime());
            user.setUpdateTime(DateUtils.currentDate());
            user.setJoinDate(DateUtils.currentDate());
            user.setRemove(0);
            user.setIntegral(0);
            user.setGender(3);
            user.setSortNo(0);
            user.setMarried(0);
            user.setChildren(0);
            user.setFirstLogin(0);
            user.setNewMember(0);
            user.setFreeze(0);
            user.setMembeType("魅享卡");
            //判断证件类型
            if (IDENTITY_CARD.equals(requestBody.getDocumenType())) {
                user.setDocumenType(User.DocumenType.identityCard);
            }
            if (ARMYMAN_CARD.equals(requestBody.getDocumenType())) {
                user.setDocumenType(User.DocumenType.armymanCard);
            }

            if (StringUtils.isNotEmpty(requestBody.getBirthday())) {
                //根据生日自动算出年龄
                Date birthDate = DateUtils.parseStr2Date(DateUtils.DATE, requestBody.getBirthday());
                String age = DateUtils.getAgeByBirth(birthDate).toString();
                user.setAge(age);

            }


            String openid = requestBody.getOpenid();
            String wxOpenid = requestBody.getWxOpenid();
            String parkingOpenId = requestBody.getParkingOpenId();
            //微信公众号openid不为空 并且小程序openid未空 注册来源是微信公众号
            if (StringUtils.isNotEmpty(wxOpenid) && StringUtils.isEmpty(openid) && StringUtils.isEmpty(parkingOpenId)) {
                //通过wxopenid查找用户如果用户存在将他的wxopenid设置为空
                List<User> userList = userRepository.findByWxOpenid(wxOpenid, 0);
                if (userList.size() > 0) {
                    for (User user1 : userList) {
                        user1.setWxOpenid(null);
                        userRepository.save(user1);
                    }
                }
                user.setWxOpenid(wxOpenid);
                // 根据openid 获取用户信息
                Map<String, String> weChatPersionInfo = getWeChatPersionInfo(wxOpenid);
                user.setMemberName(weChatPersionInfo.get("nickname"));
                user.setHeadimg(weChatPersionInfo.get("headImgUrl"));
                user.setGender(Integer.parseInt(weChatPersionInfo.get("sex")));
                user.setSource(AuthConst.LOGINSOURCE.PUBLIC_NUMBER);
            } else if (StringUtils.isEmpty(wxOpenid) && StringUtils.isNotEmpty(openid) && StringUtils.isEmpty(parkingOpenId)) {
                //通过openid查找用户如果用户存在将他的openid设置为空
                List<User> userList = userRepository.findByOpenidAndFreeze(openid, 0);
                if (userList.size() > 0) {
                    for (User user2 : userList) {
                        user2.setOpenid(null);
                        userRepository.save(user2);
                    }
                }

                //微信小程序openid不为空，并且公众号openid为空
                user.setOpenid(openid);
                user.setMemberName(requestBody.getMemberName());
                user.setHeadimg(requestBody.getHeadimg());
                user.setGender(Integer.parseInt(requestBody.getGender()));
                user.setSource(AuthConst.LOGINSOURCE.SMALL_PROGRAM);
            } else if (StringUtils.isEmpty(wxOpenid) && StringUtils.isEmpty(openid) && StringUtils.isNotEmpty(parkingOpenId)) {
                //通过openid查找用户如果用户存在将他的openid设置为空
                List<User> userList = userRepository.findByParkingOpenId(parkingOpenId, 0);
                if (userList.size() > 0) {
                    for (User user2 : userList) {
                        user2.setParkingOpenId(null);
                        userRepository.save(user2);
                    }
                }
                //微信小程序openid不为空，并且公众号openid为空
                user.setParkingOpenId(parkingOpenId);
                user.setMemberName(requestBody.getMemberName());
                user.setHeadimg(requestBody.getHeadimg());
                user.setGender(Integer.parseInt(requestBody.getGender()));
                user.setSource(AuthConst.LOGINSOURCE.PARKING_PROGRAM);
            } else {
                user.setSource(AuthConst.LOGINSOURCE.APP);
            }

            userRepository.save(user);
            //生成会员的等级关系
            userLevelService.createUserLevelRelationship(user.getId());
            //判断用户是否能拿到奖励积分和是否推送的券
            Map<String, Object> properties = new HashMap<>();
            properties.put("userId", user.getId());

            String exchange = "newUser.exchange";
            String routingKey = "newUser.reward";

            rabbitSender.sendMessageToMQ("新用户福利", properties, exchange, routingKey);

            Map<String, Object> properties1 = new HashMap<>();
            properties1.put("type", "registered");
            properties1.put("userId", user.getId());
            String exchange1 = "send.exchange";
            String routingKey1 = "send.register";
            rabbitSender.sendMessageToMQ("新用户注册成功模板推送", properties1, exchange1, routingKey1);

            return user;

        } else {
            //判断用户是用啥第一次登陆的
            User user1 = users.get(0);
            Integer freeze = user1.getFreeze();
            if (freeze == 0) {
                if (StringUtils.isNotEmpty(user1.getBirthday()) && StringUtils.isNotEmpty(user1.getName())) {
                    user1.setFirstLogin(1);
                }
                String openid = user1.getOpenid();
                String wxOpenid = user1.getWxOpenid();
                String parkingOpenId = user1.getParkingOpenId();
                System.out.println(parkingOpenId);
                String source = user1.getSource();
                if (AuthConst.LOGINSOURCE.APP.equals(source)) {
                    if (StringUtils.isNotEmpty(requestBody.getWxOpenid())) {
                        //通过wxopenid查找用户如果用户存在将他的wxopenid设置为空
                        List<User> userList = userRepository.findByWxOpenid(wxOpenid, 0);
                        if (userList.size() > 0) {
                            for (User user3 : userList) {
                                user3.setWxOpenid(null);
                                userRepository.save(user3);
                            }
                        }
                        user1.setWxOpenid(wxOpenid);

                    }
                    if (StringUtils.isNotEmpty(requestBody.getOpenid())) {
                        //通过openid查找用户如果用户存在将他的openid设置为空
                        List<User> userList = userRepository.findByOpenidAndFreeze(openid, 0);
                        if (userList.size() > 0) {
                            for (User user4 : userList) {
                                user4.setOpenid(null);
                                userRepository.save(user4);
                            }
                        }
                        user1.setOpenid(requestBody.getOpenid());
                    }
                    if (StringUtils.isNotEmpty(requestBody.getParkingOpenId())) {
                        //通过openid查找用户如果用户存在将他的openid设置为空
                        List<User> userList = userRepository.findByParkingOpenId(parkingOpenId, 0);
                        if (userList.size() > 0) {
                            for (User user5 : userList) {
                                user5.setParkingOpenId(null);
                                userRepository.save(user5);
                            }
                        }
                        user1.setParkingOpenId(requestBody.getParkingOpenId());
                    }
                }
                //判断数据是否全
                if (StringUtils.isNotEmpty(openid) && StringUtils.isNotEmpty(wxOpenid) && StringUtils.isNotEmpty(parkingOpenId)) {
                    return user1;
                }//补数据
                if (StringUtils.isEmpty(openid) && StringUtils.isNotEmpty(requestBody.getOpenid()) && StringUtils.isNotEmpty(requestBody.getParkingOpenId())) {
                    //通过openid查找用户如果用户存在将他的openid设置为空
                    List<User> userList = userRepository.findByOpenidAndFreeze(requestBody.getOpenid(), 0);
                    if (userList.size() > 0) {
                        for (User user4 : userList) {
                            user4.setOpenid(null);
                            userRepository.save(user4);
                        }
                    }
                    user1.setOpenid(requestBody.getOpenid());
                }
                if (StringUtils.isEmpty(wxOpenid) && StringUtils.isNotEmpty(requestBody.getWxOpenid()) && StringUtils.isNotEmpty(requestBody.getParkingOpenId())) {
                    //通过wxopenid查找用户如果用户存在将他的wxopenid设置为空
                    List<User> userList = userRepository.findByWxOpenid(requestBody.getWxOpenid(), 0);
                    if (userList.size() > 0) {
                        for (User user3 : userList) {
                            user3.setWxOpenid(null);
                            userRepository.save(user3);
                        }
                    }
                    user1.setWxOpenid(requestBody.getWxOpenid());
                }
                if (StringUtils.isNotEmpty(wxOpenid) && StringUtils.isNotEmpty(requestBody.getWxOpenid()) && StringUtils.isEmpty(requestBody.getParkingOpenId())) {
                    //通过wxopenid查找用户如果用户存在将他的wxopenid设置为空
                    List<User> userList = userRepository.findByParkingOpenId(requestBody.getParkingOpenId(), 0);
                    if (userList.size() > 0) {
                        for (User user3 : userList) {
                            user3.setParkingOpenId(null);
                            userRepository.save(user3);
                        }
                    }
                    user1.setParkingOpenId(requestBody.getParkingOpenId());
                }
                if (StringUtils.isNotEmpty(openid)) {
                    //通过openid查找用户如果用户存在将他的openid设置为空
                    List<User> userList = userRepository.findByOpenidAndFreeze(requestBody.getOpenid(), 0);
                    if (userList.size() > 0) {
                        for (User user4 : userList) {
                            if (!user4.equals(phone)) {
                                user4.setOpenid(null);
                                userRepository.save(user4);
                            }

                        }
                    }
                    user1.setOpenid(requestBody.getOpenid());
                }
                if (StringUtils.isNotEmpty(wxOpenid)) {
                    //通过wxopenid查找用户如果用户存在将他的wxopenid设置为空
                    List<User> userList = userRepository.findByWxOpenid(requestBody.getWxOpenid(), 0);
                    if (userList.size() > 0) {
                        for (User user3 : userList) {
                            if (!user3.equals(phone)) {
                                user3.setWxOpenid(null);
                                userRepository.save(user3);
                            }
                        }
                    }
                    user1.setWxOpenid(requestBody.getWxOpenid());
                }
                if (StringUtils.isNotEmpty(parkingOpenId)) {
                    //通过wxopenid查找用户如果用户存在将他的wxopenid设置为空
                    List<User> userList = userRepository.findByParkingOpenId(requestBody.getParkingOpenId(), 0);
                    if (userList.size() > 0) {
                        for (User user3 : userList) {
                            if (!user3.equals(phone)) {
                                user3.setParkingOpenId(null);
                                userRepository.save(user3);
                            }
                        }
                    }
                    user1.setParkingOpenId(requestBody.getParkingOpenId());
                }

                userRepository.save(user1);

                return user1;
            } else {
                return null;
            }

        }
    }


    //计算过期时间
    private String getExpirationTime() {
        //计算过期时间
        Calendar calendar = Calendar.getInstance();
        //当前年
        calendar.add(Calendar.YEAR, 1);//增加一年
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(calendar.getTime());
    }

    /**
     * 获取会员卡号
     * 卡号生成规则
     * 1.900000000自增加1
     * <p>
     * 1.先从数据库读取最新的值放到redis 可以值为memberCardNum
     * 2.将取出的值加一放到缓存中，下次再有生成卡号的业务直接去redis查出来加一保存，如果没有在查
     * <p>
     * todo
     *
     * @return
     */
    private String getMemberCardNum() throws Exception {
        int initCardNum = 900000000;
        String cardNum = redisTemplate.opsForValue().get(MEMBERCARDNUM);
        int memberCardNum;
        if (StringUtils.isEmpty(cardNum)) {
            //1.查出所有的未删除的用户并排序
            Integer remove = 0;
            List<User> users = userRepository.findAllByRemoveOrderByCreateTimeDesc(remove);
            Optional<User> first = users.stream().findFirst();
            User user = first.get();
            memberCardNum = Integer.parseInt(user.getMemberCardNum());
            if (StringUtil.isEmpty(user.getMemberCardNum())) {
                memberCardNum = initCardNum;
            }

        } else {
            memberCardNum = Integer.parseInt(cardNum);

        }
        if (initCardNum < memberCardNum) {
            memberCardNum = memberCardNum + 1;

        } else {
            memberCardNum = initCardNum;
        }
        //新增的数据替换到redis中
        redisTemplate.opsForValue().set(MEMBERCARDNUM, String.valueOf(memberCardNum));
        return String.valueOf(memberCardNum);
    }


    /**
     * 更新用户信息
     *
     * @param requestBody
     * @param userId
     * @return
     * @throws UserException
     */
    public String updateUserInfo(UserRequestBody requestBody, String userId) throws UserException {
        User user = getUserById(userId);
        //通过映射关系来赋值 //TODO 断点看一下
        BeanUtil.copyProperties(requestBody, user, true, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        //判断证件类型
        if (IDENTITY_CARD.equals(requestBody.getDocumenType())) {
            user.setDocumenType(User.DocumenType.identityCard);
        }
        if (ARMYMAN_CARD.equals(requestBody.getDocumenType())) {
            user.setDocumenType(User.DocumenType.armymanCard);
        }
        if (StringUtils.isNotEmpty(requestBody.getBirthday())) {
            //根据生日自动算出年龄
            Date birthDate = DateUtils.parseStr2Date(DateUtils.DATE, requestBody.getBirthday());
            String age = DateUtils.getAgeByBirth(birthDate).toString();
            user.setAge(age);

        }
        user.setUpdateTime(DateUtils.currentDate());
        userRepository.save(user);

        String imageId = requestBody.getImageId();
        //绑定头像图片的外建
        bandingImageShip(userId, imageId);
        return "修改用户信息成功";

    }
    /**
     * 绑定用户头像
     *
     * @param userId
     * @param imageId
     */
    private void bandingImageShip(String userId, String imageId) {
        ImageOutPut imageOutPut = new ImageOutPut();
        List<String> imageIds = new ArrayList<>();
        imageIds.add(imageId);
        imageOutPut.setForeignKeyId(userId);
        imageOutPut.setImageSource("userHead");

        //通过mq消息队列发送给资源模块绑定图片关系
//        amqpTemplate.convertAndSend("image.exchange", "image.user", JsonUtil.toJson(imageOutPut));

        Map<String, Object> properties = new HashMap<>();
        properties.put("imageIds", imageIds);

        String exchange = "image.exchange";
        String routingKey = "image.user";

        rabbitSender.sendMessageToMQ(imageOutPut, properties, exchange, routingKey);
    }


    /**
     * 根据用户id查询用户实体 （提取重复代码分装成方法）
     *
     * @param userId
     * @return
     * @throws UserException
     */
    public User getUserById(String userId) throws UserException {
        List<User> users = userRepository.findUserByIdAndRemove(userId, 0);


        if (users.size() <= 0) {
            throw new UserException("该会员不存在");
        }

        User user = users.get(0);
        if (StringUtil.isEmpty(user.getBirthday())) {
            user.setBirthday("");
        }
        if (StringUtil.isEmpty(user.getArea())) {
            user.setArea("");
        }
        if (StringUtil.isEmpty(user.getCity())) {
            user.setCity("");
        }
        if (StringUtil.isEmpty(user.getProvinces())) {
            user.setProvinces("");
        }

        return users.get(0);
    }

    /**
     * 获取用户的openid
     *
     * @param requestBody
     * @return
     */
    public String getOpenidInfo(OpenidRequestBody requestBody) {
        JSONObject json = getWeChatObj(requestBody);
        String openId;
        if (null != json) {
            Object openid = json.get("openid");
            if (null != openid) {
                openId = openid.toString();
                return openId;
            }
        }
        return null;
    }


    /**
     * @return 查看用户是否关注微信公众号
     * wxOpenid(微信公众号openid)
     */
    public boolean checkPower(String wxOpenid, String token) {
        String params = "access_token=" + token + "&openid=" + wxOpenid + "&lang=zh_CN";
        String result = Request.sendGet1(wechat_user_info_url, params);
        WeChatPersionalInfoDTO accessToKenDTO = new Gson().fromJson(result, WeChatPersionalInfoDTO.class);
        int subscribe = accessToKenDTO.getSubscribe();
        System.out.println(subscribe);
        if (subscribe == 1) {
            return true;
        } else {
            return false;
        }


    }


    /**
     * 根据APPID和secret获取token
     *
     * @return //todo 还需测试
     */
    public String getWeChatToken() {

        String token = redisTemplate.opsForValue().get(TOKEN);
        if (StringUtils.isNotEmpty(token)) {
            return token;
        } else {
            String params = "grant_type=" + AuthConst.TOKEN.GRANT_TYPE + "&appid=" + appid + "&secret=" + secret;
            String result = Request.sendGet1(AuthConst.TOKEN.WECHAT_PUBLIC_GET_ACCESS_TOKEN, params);
            AccessTokenDTO accessToKenDTO = new Gson().fromJson(result, AccessTokenDTO.class);
            String accessToken = accessToKenDTO.getAccess_token();
            System.out.println(accessToken);
            //将token缓存到redis
            //向redis中存验证码，保存时间1分钟
            redisTemplate.opsForValue().set(TOKEN, accessToken, EXPIRETOKEN, TimeUnit.SECONDS);
            return accessToken;
        }

    }

    /**
     * 根据用户公众号openid 获取个人信息
     *
     * @param wxOpenid
     */
    public Map<String, String> getWeChatPersionInfo(String wxOpenid) {
        String weChatToken = getWeChatToken();
        String params = "access_token=" + weChatToken + "&openid=" + wxOpenid + "&lang=" + "zh_CN";
        String result = Request.sendGet1(wechat_user_info_url, params);
        System.out.println(result);
        WeChatPersionalInfoDTO weChatPersionalInfoDTO = new Gson().fromJson(result, WeChatPersionalInfoDTO.class);
        String headimgurl = weChatPersionalInfoDTO.getHeadimgurl();
        String nickname = weChatPersionalInfoDTO.getNickname();
        int sex = weChatPersionalInfoDTO.getSex();
        String gender = null;
        if (sex == 1) {
            //男
            gender = "0";
        }
        if (sex == 2) {
            //女
            gender = "1";

        }
        if (sex == 0) {
            //保密
            gender = "2";
        }

        HashMap<String, String> map = new HashMap<>();

        map.put("headImgUrl", headimgurl);
        map.put("nickname", nickname);
        map.put("sex", gender);
        return map;

    }

    /**
     * 调用微信接口获取用户信息
     *
     * @param requestBody
     * @return
     */
    private JSONObject getWeChatObj(OpenidRequestBody requestBody) {
        String params;
        if (requestBody.getType() == 1) {
            params = "appid=" + appid + "&secret=" + secret + "&js_code=" + requestBody.getCode() + "&grant_type="
                    + grant;
        } else {
            params = "appid=" + parkingAppid + "&secret=" + parkingSecret + "&js_code=" + requestBody.getCode() + "&grant_type="
                    + grant;
        }
        String sr = Request.sendGet1("https://proxy.weixin.qq.com/sns/jscode2session", params);
        return JSONObject.parseObject(sr);
    }

    public String getParkingMemberPhone(RegisterRequestBody requestBody) {
        requestBody.setType(2);
        JSONObject json = getWeChatObj(requestBody);
        if (!json.containsKey("session_key")) {
            return null;
        }
        String sessionKey = json.get("session_key").toString();
        String result;
        try {
            result = AESUtil.wxDecrypt(requestBody.getEncryptedData(), sessionKey, requestBody.getIv());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return result;
    }

    public String getMemberPhone(OpenidRequestBody requestBody) {
        JSONObject json = getWeChatObj(requestBody);
        if (!json.containsKey("session_key")) {
            return null;
        }
        String sessionKey = json.get("session_key").toString();
        String result;
        try {
            result = AESUtil.wxDecrypt(requestBody.getEncryptedData(), sessionKey, requestBody.getIv());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return result;
    }

    public PageDTO<User> findAllUsers(PageRequestBody requestBody) throws UserException {
        Integer page = requestBody.getPage() == null ? 0 : requestBody.getPage();
        Integer size = requestBody.getSize() == null ? 100 : requestBody.getSize();
        String sortBy = StringUtil.isEmpty(requestBody.getSort()) ? "createTime" : requestBody.getSort();
        Sort sort = requestBody.isAsc() ? new Sort(Sort.Direction.ASC, sortBy) : new Sort(Sort.Direction.DESC, sortBy);
        Pageable pageable = PageRequest.of(page, size, sort);
        Page<User> findAll = userRepository.findAll(pageable);
        if ((findAll.getSize()) == 0) {
            throw new UserException("用户列表查询失败");
        }
        PageDTO<User> pageDTO = new PageDTO<>();
        pageDTO.setTotal(findAll.getTotalElements());
        pageDTO.setList(findAll.getContent());
        pageDTO.setTotalPage(findAll.getTotalPages());
        pageDTO.setPage(page);
        pageDTO.setPageSize(size);
        return pageDTO;
    }

    /**
     * 根据关键词查询会员，会员积分等功能使用
     *
     * @param keyword
     * @return
     */
    public List<User> findListByKeyword(String keyword) {
        List<User> userList = userRepository.findAll((Specification<User>) (root, query, criteriaBuilder) -> {
            Predicate p = criteriaBuilder.like(root.get("memberCardNum").as(String.class), "%" + keyword + "%");
            Predicate p1 = criteriaBuilder.or(criteriaBuilder.like(root.get("phone").as(String.class), "%" + keyword + "%"), p);
            Predicate p2 = criteriaBuilder.or(criteriaBuilder.like(root.get("memberName").as(String.class), "%" + keyword + "%"), p1);
            return query.where(p2).getRestriction();
        });
        return userList;
    }

    /**
     * 根据条件查询会员
     *
     * @param requestBody
     * @return
     */
    public PageDTO<User> queryCondition(UserRequestBody requestBody) {
        Integer page = null == requestBody.getPage() ? 0 : requestBody.getPage();
        Integer size = null == requestBody.getSize() ? 10 : requestBody.getSize();
        boolean asc = requestBody.isAsc();
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        String keyword = requestBody.getKeyword();
        String fromDate = requestBody.getFromDate();
        String toDate = requestBody.getToDate();
        Integer fromInt = requestBody.getFromInt();
        Integer toInt = requestBody.getToInt();
        String gender = requestBody.getGender();
        String age = requestBody.getAge();
        String email = requestBody.getEmail();
        String birthday = requestBody.getBirthday();
        String joinDate = requestBody.getJoinDate();
        String identityNum = requestBody.getIdentityNum();
        String source = requestBody.getSource();
        String integral = requestBody.getIntegral();
        String birthdayFrom = requestBody.getBirthdayFrom();
        String birthdayTo = requestBody.getBirthdayTo();
        Pageable pageable = PageRequest.of(page, size, sort);
        Page<User> paged = userRepository.findAll((Specification<User>) (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            // 创建具体查询条件
            if (StringUtils.isNotEmpty(fromDate)) {
                Date from = DateUtils.strToDate(fromDate, DateUtils.DATE);
                predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime").as(Date.class), from));
            }
            if (StringUtils.isNotEmpty(toDate)) {
                Date to = DateUtils.getEndOfDay(DateUtils.strToDate(toDate, DateUtils.DATE));
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime").as(Date.class), to));
            }
            if (StringUtils.isNotEmpty(age)) {
                predicates.add(criteriaBuilder.like(root.get("age").as(String.class), "%" + age + "%"));
            }
            if (StringUtils.isNotEmpty(birthdayFrom)) {
                Date from = DateUtils.strToDate(birthdayFrom, DateUtils.DATE);
                predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("birthday").as(Date.class), from));
            }
            if (StringUtils.isNotEmpty(birthdayTo)) {
                Date to = DateUtils.getEndOfDay(DateUtils.strToDate(birthdayTo, DateUtils.DATE));
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("birthday").as(Date.class), to));
            }
            if (StringUtils.isNotEmpty(keyword)) {
                Predicate p1 = criteriaBuilder.like(root.get("memberName").as(String.class), "%" + keyword + "%");
                Predicate p2 = criteriaBuilder.or(criteriaBuilder.like(root.get("phone").as(String.class), "%" + keyword + "%"), p1);
                Predicate p3 = criteriaBuilder.or(criteriaBuilder.like(root.get("name").as(String.class), "%" + keyword + "%"), p2);
                Predicate p4 = criteriaBuilder.or(criteriaBuilder.like(root.get("memberCardNum").as(String.class), "%" + keyword + "%"), p3);
                Predicate p5 = criteriaBuilder.or(criteriaBuilder.like(root.get("membeType").as(String.class), "%" + keyword + "%"), p4);

                predicates.add(p5);
            }
            if (null != fromInt) {
                predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("integral").as(Integer.class), fromInt));
            }

            if (null != toInt) {
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("integral").as(Integer.class), toInt));
            }

            if (StringUtils.isNotEmpty(email)) {

                predicates.add(criteriaBuilder.like(root.get("email").as(String.class), "%" + email + "%"));
            }
            if (StringUtils.isNotEmpty(identityNum)) {

                predicates.add(criteriaBuilder.like(root.get("identityNum").as(String.class), "%" + identityNum + "%"));
            }
            if (StringUtils.isNotEmpty(birthday)) {

                predicates.add(criteriaBuilder.like(root.get("birthday").as(String.class), "%" + birthday + "%"));
            }
            if (StringUtils.isNotEmpty(source)) {

                predicates.add(criteriaBuilder.like(root.get("source").as(String.class), "%" + source + "%"));
            }
            if (StringUtils.isNotEmpty(gender)) {

                predicates.add(criteriaBuilder.equal(root.get("gender"), Integer.valueOf(gender)));
            }
            if (StringUtils.isNotEmpty(integral)) {

                predicates.add(criteriaBuilder.equal(root.get("integral"), Integer.valueOf(integral)));
            }
            predicates.add(criteriaBuilder.equal(root.get("remove"), 0));
            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        }, pageable);
        PageDTO<User> dto = new PageDTO<>();
        dto.setTotal(paged.getTotalElements());
        dto.setAsc(asc);
        dto.setKeyword(requestBody.getKeyword());
        dto.setFromDate(fromDate);
        dto.setToDate(toDate);
        dto.setList(paged.getContent());
        dto.setPage(page);
        dto.setPageSize(size);
        dto.setFromInt(fromInt);
        dto.setToInt(toInt);
        dto.setTotalPage(paged.getTotalPages());
        return dto;
    }



    /**
     * 结算积分
     *
     * @param userId
     * @param integralPoint
     * @param tradeAction
     * @return //1.根据会员ID查询会员
     * //2.拿到会员积分后进行积分的结算
     * //3.将计算结果保存
     */
    public String settlementOfIntegral(String userId, Integer integralPoint, Integer tradeAction) {
        User user = userRepository.findById(userId).orElse(null);
        assert user != null;
        Integer integral = user.getIntegral();
        //先对用户积分进行审核（待确认，估计不用审了，只有在积分够的情况下才会进行积分的抵扣）
        //进行积分的结算
        //先判断是添加还是扣除 0 添加 1 扣除
        if (tradeAction == 0) {
            integral = integral + integralPoint;
        }
        if (tradeAction == 1) {
            integral = integral - integralPoint;
            //todo 抵扣会不会是负数结果有待测试
            if (integral < 0) {
                return null;
            }


        }
        user.setIntegral(integral);
        userRepository.save(user);
        return integral.toString();

    }




    /**
     * 解除绑定关系
     *
     * @param source
     */
    public boolean unbindReleationShip(String source, String userId) {
        User user = userRepository.findById(userId).orElse(null);
        assert user != null;
        if (OFFICIAL_ACCOUNTS.equals(source)) {
            user.setWxOpenid(null);
        }
        if (WECHAT_APPLET.equals(source)) {
            user.setOpenid(null);
        }
        userRepository.save(user);

        return true;
    }


    /**
     * 查询积分明细专用
     *
     * @param userIds
     * @return
     */
    public List<User> findUsers(Set<String> userIds) {
        List<User> users = userRepository.findAllById(userIds);
        return users;
    }

    /**
     * 查询积分明细专用
     *
     * @param phones
     * @return
     */
    public List<User> findUsersByPhone(List<String> phones) {
        List<User> users = new ArrayList<>();
        for (String phone : phones) {
            User user = userRepository.findByPhoneAndRemove(phone, 0);
            if (user != null) {
                users.add(user);
            }
        }
        return users;
    }

    public List<UserDTO> queryByIdList(List<String> foreignKeyIds) {
        List<User> users = userRepository.findAllById(foreignKeyIds);
        List<UserDTO> userDTOS = new ArrayList<>();
        for (User user : users) {
            UserDTO userDTO = new UserDTO();
            //通过映射关系来赋值 //TODO 断点看一下
            BeanUtils.copyProperties(user, userDTO);

            userDTOS.add(userDTO);
        }

        return userDTOS;
    }


    public User findUserByPhone(String phone) {
        List<User> users = userRepository.findUserByPhoneAndRemove(phone, 0);
        if (users.size() <= 0) {
            return null;
        }
        return users.get(0);


    }

    public User findUserByCard(String memberCardNum) {
        List<User> users = userRepository.findUserByMemberCardNumAndRemove(memberCardNum, 0);
        if (users.size() <= 0) {
            return null;
        }
        return users.get(0);


    }

    /**
     * 根据用户id查询会员等级并修改
     *
     * @param userId
     */
    public void updateUserLevelById(String userId, String levelName) {

        User user = userRepository.findById(userId).orElse(null);
        assert user != null;
        user.setMembeType(levelName);
        userRepository.save(user);

    }


    /**
     * 冻结用户
     *
     * @param userId
     */
    public User changeUserStatus(String userId) throws UserException {
        if (StringUtil.isEmpty(userId)) {
            throw new UserException("缺少必要参数：用户ID");
        }
        User user = userRepository.findById(userId).orElse(null);
        if (null == user) {
            throw new UserException("该用户不存在");
        }
        if (user.getFreeze() == 0) {
            user.setFreeze(1);
            User save = userRepository.save(user);
            return save;
        } else {
            user.setFreeze(0);
            User save = userRepository.save(user);
            return save;
        }

    }


    //获取微信的openId并注册
    public String getOpenId(RegisterRequestBody requestBody) {
        JSONObject json = getWeChatObj(requestBody);
        String openId = null;
        if (null != json) {
            Object openid = json.get("openid");
            if (null != openid) {
                openId = openid.toString();
            }
        }

        return openId;
    }

    private JSONObject getWeChatObj(RegisterRequestBody requestBody) {
        String params;
        /*String params = "appid=" + AuthConst.WECHAT.ID + "&secret=" + AuthConst.WECHAT.SECRET + "&js_code=" + requestBody.getCode() + "&grant_type="
                + AuthConst.WECHAT.GRANT;*/
        if (requestBody.getType() == 1) {
            params = "appid=" + appid + "&secret=" + secret + "&js_code=" + requestBody.getCode() + "&grant_type="
                    + grant;
        } else {
            params = "appid=" + parkingAppid + "&secret=" + parkingSecret + "&js_code=" + requestBody.getCode() + "&grant_type="
                    + grant;
        }
        String sr = Request.sendGet1("https://api.weixin.qq.com/sns/jscode2session", params);
        return JSONObject.parseObject(sr);
    }

    public User getUserPhone(String wxOpenid) {
        return userRepository.findByWxOpenidAndFreeze(wxOpenid, 0);
    }
    public Boolean checkBalance(String userId, int integralPrice) {
        User user = userRepository.findById(userId).orElse(null);
        Integer integral1 = user.getIntegral();
        int i = integral1 - integralPrice;
        if (i >= 0) {
            return true;
        }
        return false;
    }

    /**
     * 根据小程序openid查询用户信息
     *
     * @param openid
     * @return
     */
    public User findUserByOpeId(String openid, String source) {
        List<User> byOpenidAndFreeze;

        if (source != null && source.equals(AuthConst.LOGINSOURCE.PARKING_PROGRAM)) {
            byOpenidAndFreeze = userRepository.findByParkingOpenId(openid, 0);
        } else {
            byOpenidAndFreeze = userRepository.findByOpenidAndFreeze(openid, 0);
        }

        if (byOpenidAndFreeze.size() <= 0) {
            return null;
        }
        User user = byOpenidAndFreeze.get(0);
        if (user == null) {
            return null;
        }


        userRepository.save(user);
        return user;

    }

    /**
     * 根据小程序openid查询用户信息
     *
     * @param openid
     * @return
     */
    public User findUserByParkingOpenId(String openid) {

        List<User> byOpenidAndFreeze = userRepository.findByParkingOpenId(openid, 0);
        if (byOpenidAndFreeze.size() <= 0) {
            return null;
        }
        User user = byOpenidAndFreeze.get(0);
        if (user == null) {
            return null;
        }


        userRepository.save(user);
        return user;

    }


    public String updateMembercard() {
        List<User> all = userRepository.findAll();
        for (int i = 0; i <= all.size(); i++) {
            User user = all.get(i);
            String memberCardNum = user.getMemberCardNum();
            int i1 = Integer.parseInt(memberCardNum);
            int c = i1 + i;
            String s = String.valueOf(c);
            user.setMemberCardNum(s);
            userRepository.save(user);
        }
        return "修改成功";
    }


    public void updateUserUpdateTime(String openid){
        userRepository.updateUserUpdateTime(openid);
    }
}
